#define _SGDEF_

#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <dos.h>
#include <io.h>
#include <fcntl.h>
#include <string.h>
#include <bios.h>
#include <errno.h>
#include "rad.h"
#include "smack.h"
#include "dosext.h"
#include "svga.h"

#include "sprite.h"
#include "player.h"
#include "sound.h"
#include "palette.h"
#include "debug.h"
#include "event.h"
#include "menu.h"
#include "xenon.h"
#include "sgdef.h"

extern  long g_currentscenenumber;
extern long g_nextscenenumber;
extern int buffercopylongs(char *, char *, long);
extern TARGET g_targstack[];


void CreateSaveGameTemplate()
{
	char *sgtemp;
	long sg;

	unlink("firewall.sg");
	if((sg=open("firewall.sg",(O_WRONLY | O_CREAT | O_BINARY),S_IRWXU)) <0)
	{
		fatalerror("Couldn't open firewall.sg \n");
	}
	sgtemp = malloc((MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH));
	memset(sgtemp,0,(MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH));
	write(sg,sgtemp,(MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH));
	close(sg);
	for(sg =0; sg < MAX_SAVEDGAMES; ++sg)
	 unlink(g_sgnames[sg]);
}

void LoadSavedGamesText()
{
	long sg,sgf;
	struct stat fs;

	if((sgf=open("firewall.sg",(O_RDONLY | O_BINARY))) <0)
	 CreateSaveGameTemplate();
#if 1
    else
	 {
	    fstat(sgf, &fs);
		if(fs.st_size != (MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH))
		 {
		  close(sgf);
		  unlink("firewall.sg");
	      CreateSaveGameTemplate();
         }
	 }
#endif

	if((sgf=open("firewall.sg",(O_RDONLY | O_BINARY))) <0)
		fatalerror("Could not access firewall\.sg file\n");

	memset(&g_savedgamestext,0,(MAX_SAVEDGAMES * sizeof(SAVEGAMETEXT)));

	for(sg = 0; sg < MAX_SAVEDGAMES; ++sg)
	{
		read(sgf,g_savedgamestext[sg].saveid,SAVEGAMETEXTLENGTH);
		if(!strlen(g_savedgamestext[sg].saveid))  //Has an id 
			unlink(g_sgnames[sg]);
		else if(access(g_sgnames[sg],0) < 0) //Check if file there
			memset(g_savedgamestext[sg].saveid,0,SAVEGAMETEXTLENGTH);
	}
	close(sgf);
}

void LoadGame(long gametoload)
{
	long sgf,encryptkey,*sglong;
	long readsize,sizeread;
	char errormsg[32];
	struct stat fs;

	if((sgf=open(g_sgnames[gametoload],(O_RDONLY | O_BINARY))) <0)
	{
		sprintf(errormsg,"Couldn't open %s for read\n", g_sgnames[gametoload]);
		fatalerror(errormsg);
	}

	fstat(sgf, &fs);

	readsize = sizeof(SAVEGAME);
	sizeread = read(sgf,&g_savedgame,sizeof(SAVEGAME));
	if(fs.st_size == (sizeof(SAVEGAME) - 8)) //very old, no encryption
		goto endit;
	
	else if(fs.st_size == (sizeof(SAVEGAME))) //Encrypted file
	{
		encryptkey = g_savedgame.nextscenenumber;
		sglong = (long *) &g_savedgame;
		while(sglong < ((char *) &g_savedgame + sizeof(SAVEGAME)))
		{
			*sglong = *sglong ^ encryptkey;
			sglong++;
		}
	}
	else if(fs.st_size == (sizeof(SAVEGAME) + 4)) //Encrypted file
	{
		read(sgf,&encryptkey,sizeof(long));
		sglong = (long *) &g_savedgame;
		while(sglong < ((char *) &g_savedgame + sizeof(SAVEGAME)))
		{
			*sglong = *sglong ^ encryptkey;
			sglong++;
		}
	}
endit:
	close(sgf);
}

void SaveGame(long gametosave)
{
	long targ,sg,sgn,encryptkey,*sglong,sg1,sg2;
	long x,x1,x2;
	char errormsg[32],*q;
	char godcheck[SAVEGAMETEXTLENGTH],*g_cheatsc;
	FILE *testf;
	char  savesg[(MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH)];

	memset(godcheck,0,SAVEGAMETEXTLENGTH);
	memcpy(godcheck,g_savedgamestext[gametosave].saveid,SAVEGAMETEXTLENGTH);

	x = SAVEGAMETEXTLENGTH -1;

	for(; x >=0; x = (x -4))
	{
		for(x1 =(x -3),x2 =0; x1 <= x; ++x1,++x2)
		if(g_savedgamestext[gametosave].saveid[x-x2])
			godcheck[x1] = ~g_savedgamestext[gametosave].saveid[x-x2];
		else
			godcheck[x1] =  g_savedgamestext[gametosave].saveid[x-x2];
	}
	g_cheatsc = (char *) g_cheats;
	for(x=0; x < NUMCHEATS; ++x)
	{
		if(!strncmp(godcheck,g_cheatsc, SAVEGAMETEXTLENGTH))
		{
			memcpy(g_savedgamestext[gametosave].saveid,
					 g_lastname,SAVEGAMETEXTLENGTH);
			GodPower();
			return;
		}
		g_cheatsc = g_cheatsc + (sizeof(long) * 3);
	}
	if((sg=open(g_sgnames[gametosave],
					(O_WRONLY | O_CREAT | O_BINARY),S_IRWXU))<0)
	{
		sprintf(errormsg,"Couldn't open %s for write \n", 
					g_sgnames[gametosave]);
		fatalerror(errormsg);
	}
	g_savedgame.pressetgame.lives       = g_player.lives;
	g_savedgame.pressetgame.hitpoints   = g_player.hitpoints;
	g_savedgame.pressetgame.scenenumber = g_currentscenenumber;
	g_savedgame.pressetgame.framenumber = g_curframe;

	g_savedgame.pressetgame.secrroomsolved = 0;
	
   if(g_secrroomsolved)
	g_savedgame.pressetgame.secrroomsolved |= SECRROOMSOLVED;
   if(g_switched)
	g_savedgame.pressetgame.secrroomsolved |= SECRROOMSWITCH;

	g_savedgame.pressetgame.selectedweap = g_selectedweap;
	g_savedgame.pressetgame.selectedtool = g_selectedtool;

	memcpy(&g_savedgame.pressetgame.tools,&g_tools,
				 (MAX_CYBTOOLS * sizeof(UTILITY)));

	memcpy(&g_savedgame.pressetgame.weaps,&g_weaps,
			((MAX_CYBWEAPONS + MAX_RWDWEAPONS) * sizeof(UTILITY)));

    buffercopylongs(&g_savedgame.pressetgame.sceneentry,g_scenentry,(sizeof(long) * 12));
    memcpy(&g_savedgame.pressetgame.playedclue,g_playedclue,
	   (NUMCLUES * sizeof(short)));

    memcpy(&g_savedgame.prevsetgame,&g_setgame,sizeof(SETGAME));

   /*Now we're into the big stuff. The screen and target info*/
	buffercopylongs(g_savedgame.palette,g_palette,PALSIZE);

	buffercopylongs(g_savedgame.framebuffer,smackBuffer2,
						 SAVESCREENBUFFERSIZE);

	g_savedgame.numtargets = g_numtargets;
	for(targ = 0; targ <= g_numtargets; ++targ)
		memcpy(&g_savedgame.targstatus[targ],
				 &g_targstack[targ].status,sizeof(TARGETSTATUS));

	g_savedgame.nextscenenumber = g_nextscenenumber;

#if 1
	q = (char *) &encryptkey;
	*q = g_savedgamestext[gametosave].saveid[0];
	*(q+1) = g_savedgamestext[gametosave].saveid[1];
	*(q+2) = g_savedgamestext[gametosave].saveid[2];
	*(q+3) = g_savedgamestext[gametosave].saveid[3];
	encryptkey = encryptkey >> 1;
	sglong = (long *) &g_savedgame;
	while(sglong < ((char *) &g_savedgame + sizeof(SAVEGAME)))
	{
		*sglong = *sglong ^ encryptkey;
		sglong++;
	}
#endif

	write(sg,&g_savedgame,sizeof(SAVEGAME));
#if 1
	write(sg,&encryptkey,sizeof(long));
#endif
	close(sg);

if((sg=open("firewall.sg",(O_WRONLY | O_CREAT | O_BINARY),S_IRWXU))<0)
 {
  sprintf(errormsg,"Couldn't open firewall.tmp for write \n");
  fatalerror(errormsg);
 }

 for(sgn = 0; sgn < MAX_SAVEDGAMES; ++sgn)
   write(sg,g_savedgamestext[sgn].saveid,SAVEGAMETEXTLENGTH);

 close(sg);
 

#if 0
//This following code is very slow and stupid,
// but so is WINDOWS 95, which is the reason I had
// to do it, because the demon geek Bill Gates
// did not support the rename function properly!!
 if((sg1=open("firewall.sg1",(O_WRONLY | O_CREAT | O_BINARY),S_IRWXU))<0)
  {
   sprintf(errormsg,"Couldn't open firewall.sg1 for write \n");
   fatalerror(errormsg);
  }

 if((sg2=open("firewall.sg",(O_RDONLY | O_BINARY))) <0)
  {
   sprintf(errormsg,"Couldn't open firewall.sg for read \n");
   fatalerror(errormsg);
  }

// Save off old firewall.sg to file
  read(sg2,&savesg,(MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH));
  write(sg1,&savesg,(MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH));

  close(sg1);
  close(sg2);

// Now save off new firewall.sg
 if((sg1=open("firewall.sg",(O_WRONLY | O_CREAT | O_BINARY),S_IRWXU))<0)
  {
   sprintf(errormsg,"Couldn't open firewall.sg for write \n");
   fatalerror(errormsg);
  }

 if((sg2=open("firewall.tmp",(O_RDONLY | O_BINARY))) <0)
  {
   sprintf(errormsg,"Couldn't open firewall.tmp for read \n");
   fatalerror(errormsg);
  }

  read(sg2,&savesg,(MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH));
  write(sg1,&savesg,(MAX_SAVEDGAMES * SAVEGAMETEXTLENGTH));
  close(sg1);
  close(sg2);
  unlink("firewall.tmp");
#endif
}

void RestoreGame()
{
	g_currentscenenumber = (long) g_savedgame.pressetgame.scenenumber;
	g_nextscenenumber    = (long) g_savedgame.nextscenenumber;
	g_restoreframe       = (long) g_savedgame.pressetgame.framenumber;
	g_player.hitpoints   = (long) g_savedgame.pressetgame.hitpoints;
	g_player.lives       = (long) g_savedgame.pressetgame.lives;
	g_selectedtool       = g_savedgame.pressetgame.selectedtool;
	g_selectedweap       = g_savedgame.pressetgame.selectedweap;

	if(g_savedgame.pressetgame.secrroomsolved & SECRROOMSOLVED)
	  g_secrroomsolved   = TRUE;
	else
	  g_secrroomsolved   = FALSE;

	if(g_savedgame.pressetgame.secrroomsolved & SECRROOMSWITCH)
	  g_switched         = TRUE;
    else
	  g_switched         = FALSE;

	memcpy(&g_scenentry,g_savedgame.pressetgame.sceneentry,(12*sizeof(long)));
	memcpy(&g_playedclue,g_savedgame.pressetgame.playedclue,(NUMCLUES * sizeof(short)));

	memcpy(&g_setgame,&g_savedgame.prevsetgame,sizeof(SETGAME));

	memcpy(&g_tools,g_savedgame.pressetgame.tools,(MAX_CYBTOOLS * sizeof(UTILITY)));

	memcpy(&g_weaps,g_savedgame.pressetgame.weaps,
			((MAX_CYBWEAPONS + MAX_RWDWEAPONS) * sizeof(UTILITY)));


	buffercopylongs(g_palette,g_savedgame.palette,PALSIZE);
	buffercopylongs(smackBuffer2,g_savedgame.framebuffer,SAVESCREENBUFFERSIZE);
	g_branchwarn = 0;
}

void ResetGame()
{
	memcpy(&g_tools,g_setgame.tools,
	                 (MAX_CYBTOOLS * sizeof(UTILITY)));

	memcpy(&g_weaps,g_setgame.weaps,
			((MAX_CYBWEAPONS + MAX_RWDWEAPONS) * sizeof(UTILITY)));

	g_selectedtool   = g_setgame.selectedtool;
	g_selectedweap   = g_setgame.selectedweap;
	g_secrroomsolved = g_setgame.secrroomsolved;

	memcpy(&g_tools,&g_setgame.tools,(MAX_CYBTOOLS * sizeof(UTILITY)));

	memcpy(&g_weaps,&g_setgame.weaps,
			((MAX_CYBWEAPONS + MAX_RWDWEAPONS) * sizeof(UTILITY)));

#if 0
	if(g_currentscenenumber > SC_GRWALL)
	{
		for(tool =0; tool<(MAX_CYBTOOLS);++tool)
		{
			g_tools[tool].toolaquired = g_setgame.tools[tool].toolaquired;
			if(g_tools[tool].toolaquired)
				g_selectedtool = tool;
		}
	}
	for(weap =0; weap<(MAX_CYBWEAPONS + MAX_RWDWEAPONS);++weap)
	{
		g_weaps[weap].weapaquired = g_setgame.weaps[weap].weapaquired;
		if(g_weaps[weap].weapaquired)
			g_selectedweap = weap;
	}
#endif
}

void SetGame()
{
	memset(&g_setgame,0,sizeof(SETGAME));

	g_setgame.lives = g_player.lives;

	g_setgame.selectedtool = g_selectedtool;
	g_setgame.selectedweap = g_selectedweap;
	memcpy(&g_setgame.tools,&g_tools,(MAX_CYBTOOLS * sizeof(UTILITY)));
	memcpy(&g_setgame.weaps,&g_weaps,
			((MAX_CYBWEAPONS + MAX_RWDWEAPONS) * sizeof(UTILITY)));
}

void GodPower()
{

if(g_currentscenenumber > SC_GRWALL)
{
		g_selectedweap = WP_HexRipper1;
		g_selectedtool = TL_Passcode1;
		g_weaps[WP_Cyclone].weapaquired    = TRUE;
		g_weaps[WP_AIRES].weapaquired      = TRUE;
		g_weaps[WP_StunHammer].weapaquired = TRUE;
		g_weaps[WP_CodeSlammer].weapaquired = TRUE;
		g_weaps[WP_HexRipper1].weapaquired = TRUE;
		g_weaps[WP_HexRipper2].weapaquired = TRUE;

		g_tools[TL_Passcode1].toolaquired = TRUE;
		g_tools[TL_Passcode2].toolaquired = TRUE;
		g_tools[TL_TraceCutter1].toolaquired = TRUE;
		g_tools[TL_TraceCutter2].toolaquired = TRUE;
		g_tools[TL_LabKey].toolaquired = TRUE;
		g_tools[TL_DamageRepair].toolaquired = TRUE;
}

		g_godpower = 0x77;
}
